
#include <string.h>
#include <stdlib.h>

#include "app_error.h"

//#include "ota_req_handle.h"

#include "xota+pb+proto.h"
#include "crc16.h"


// #include "nrf_log.h"
// #include "nrf_log_ctrl.h"




static void xpb_proto_pack( 	pb_proto_data_t * pb_data, 
							const uint8_t * payload, 
							uint16_t size,
							pb_resp_handle_t p_resp_handle)
{
	if( 	pb_data == NULL 
		|| 	payload == NULL 
		|| p_resp_handle == NULL
	) {
		return; 
	}
	
	uint8_t* pb_proto_buff = (uint8_t*)malloc( size + PB_PROTO_HEAD_SIZE ); 
	if( pb_proto_buff == NULL ){
		return; 
	}
	
	pb_data->length = size; 
	pb_data->crc = crc16_compute( payload, size, NULL ); 
	
	
	pb_proto_buff[ 0 ] = pb_data->magic; 
	pb_proto_buff[ 1 ] = pb_data->flag; 
	pb_proto_buff[ 2 ] = (uint8_t)( pb_data->length >> 0 ); 
	pb_proto_buff[ 3 ] = (uint8_t)( pb_data->length >> 8 ); 
	pb_proto_buff[ 4 ] = (uint8_t)( pb_data->crc >> 0 ); 
	pb_proto_buff[ 5 ] = (uint8_t)( pb_data->crc >> 8 ); 
	pb_proto_buff[ 6 ] = (uint8_t)( pb_data->tid >> 0 ); 
	pb_proto_buff[ 7 ] = (uint8_t)( pb_data->tid >> 8 ); 
	
	memcpy( pb_proto_buff + PB_PROTO_HEAD_SIZE, payload, size ); 
	
	// transfer to tx handle 
	p_resp_handle ( pb_proto_buff, size + PB_PROTO_HEAD_SIZE ); 
	
	// free it 
	free( pb_proto_buff ); 	
}




uint32_t xpb_proto_data_consume(  pb_proto_data_t * pb_data , pb_resp_handle_t pb_resp_handle)
{
	if( pb_data == NULL || pb_data->payload == NULL )
		return NRF_ERROR_NULL; 
	
	/*
	ota_req_t 	ota_req; 
	ota_resp_t	ota_resp; 
	
	// check crc of packet, 
	uint16_t crc = crc16_compute( pb_data->payload, pb_data->length, NULL ); 
	if( crc != pb_data->crc ){
		//return current bootloader state( initial/updating/done )
		ota_req.req_type = OTA_OPCODE_QUERY; 
		NRF_LOG_INFO("pbProto get an invalid crc\r\n");
	}
	else{
		NRF_LOG_INFO("pbProto get a request = 0x%X\r\n",  pb_data->payload[ PB_PROTO_COMMAND_OFFSET ]);
		switch( pb_data->payload[ PB_PROTO_COMMAND_OFFSET ] )
		{
			case OTA_OPCODE_INIT:
				ota_req.req_type = OTA_OPCODE_INIT; 
				ota_req.p_req = &pb_data->payload[ PB_PROTO_PAYLOAD_1_KEY_OFFSET ];
				ota_req.req_len = pb_data->length - 1; 
				break; 
			
			case OTA_OPCODE_WRITE:
				ota_req.req_type = OTA_OPCODE_WRITE; 
				ota_req.p_req = &pb_data->payload[ PB_PROTO_PAYLOAD_1_KEY_OFFSET ];
				ota_req.req_len = pb_data->length - 1; 
				break; 
			
			case OTA_OPCODE_EXECUTE:
				ota_req.req_type = OTA_OPCODE_EXECUTE; 
				break; 
			
			case OTA_OPCODE_QUERY:
				ota_req.req_type = OTA_OPCODE_QUERY; 
				break; 
			
			case OTA_OPCODE_RESET:
				ota_req.req_type = OTA_OPCODE_RESET; 
				break; 
			
			default:
				ota_req.req_type = OTA_OPCODE_QUERY; 
				break; 
		}
	}
	
	if( (pb_data->flag & PB_PROTO_HEAD_FLAG_CRYPTO_MASK) > 0 ){
		ota_req.has_crypto = true; 
		ota_req.crypto_type = PB_PROTO_HEAD_FLAG_CRYPTO_MASK & pb_data->flag; 
	}
	else{
		ota_req.has_crypto = false; 
	}
	
	
	// call pb_proto_data_consume 
//	ota_data_req_handler_on_req( &ota_req, &ota_resp ) ; 
	switch( ota_resp.res_type )
	{
		case OTA_RES_TYPE_POS_RESP: // has positive response 
			pb_data->flag = PB_PROTO_FLAG_DEFAULT; 
			pb_proto_pack( pb_data, ota_resp.res_array, ota_resp.res_len, pb_resp_handle ); 
			break; 
		case OTA_RES_TYPE_ERROR_CODE:
			pb_data->flag = PB_PROTO_FLAG_RESP_ERROR; 
			pb_proto_pack( pb_data, ota_resp.res_array, ota_resp.res_len, pb_resp_handle ); 
			break; 
		default:
			// do nothing 
			break; 
	}
	
	if( ota_resp.res_type == OTA_RES_TYPE_POS_RESP ){
		return NRF_SUCCESS; 
	}
	else{
		return NRF_ERROR_INVALID_PARAM; 
	}	 */
	return 0; 
}



